using System;
using System.Diagnostics.Contracts;
using System.Windows.Input;

namespace Sundstrom.Mvvm.Command 
{
    /// <summary>
    /// Relay command. 
    /// Based on source: http://wpftutorial.net/DelegateCommand.html
    /// </summary>
	public class RelayCommand<T> : ICommand<T>
	{
		private readonly Func<T, bool> _canExecute;
		private readonly Action<T> _execute;

		public event EventHandler CanExecuteChanged;

		public RelayCommand(Action<T> execute) 
		{
            Contract.Requires<ArgumentNullException>(execute != null);

            _execute = execute;
            _canExecute = null;
		}

		public RelayCommand(Action<T> execute, 
		                       Func<T, bool> canExecute)
		{
            Contract.Requires<ArgumentNullException>(execute != null);
            Contract.Requires<ArgumentNullException>(canExecute != null);

			_execute = execute;
			_canExecute = canExecute;
		}

		bool ICommand.CanExecute(object parameter)
		{
            return CanExecute((T)parameter);
		}

        void ICommand.Execute(object parameter)
		{
			Execute((T)parameter);
		}

		public void RaiseCanExecuteChanged()
		{
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
		}

        public void Execute(T parameter)
        {
            _execute(parameter);
        }

        public bool CanExecute(T parameter)
        {
            if (_canExecute == null)
			{
				return true;
			}

			return _canExecute(parameter);
        }
	}
}